/*
 * PlayerExt.cpp
 *
 *  Created: 2013-07-11
 *   Author: terry
 */

#include "stdafx.h"

#include "H264Player.h"

#define MONITOR_EXPORTS
#include "media.h"

#include <map>
#include "TCriticalSection.h"


class CallBackContext
{
public:
    long port;
    VideoCallBack cb;
    long user;

    CallBackContext():
        port(),
        cb(),
        user()
    {
    }
};

typedef std::map< HANDLE, CallBackContext > CallBackContextTable;

class PlayerExtend
{
public:
    CallBackContextTable    m_cbContextTable;
    comn::CriticalSection   m_cs;

};

PlayerExtend*   g_pExtend = NULL;


void XX_DEC_Init()
{
    g_pExtend = new PlayerExtend();
}

void XX_DEC_Uninit()
{
    delete g_pExtend;
    g_pExtend = NULL;
}

void addCallBackContext(HANDLE handle, const CallBackContext& context)
{
    comn::AutoCritSec lock(g_pExtend->m_cs);
    g_pExtend->m_cbContextTable[handle] = context;
}

bool findCallBackContext(HANDLE handle, CallBackContext& context)
{
    comn::AutoCritSec lock(g_pExtend->m_cs);
    bool found = false;
    CallBackContextTable::iterator it = g_pExtend->m_cbContextTable.find(handle);
    if (it != g_pExtend->m_cbContextTable.end())
    {
        context = it->second;
        found = true;
    }
    return found;
}

void removeCallBackContext(HANDLE handle)
{
    comn::AutoCritSec lock(g_pExtend->m_cs);
    g_pExtend->m_cbContextTable.erase(handle);
}





MONITOR_API bool XX_DEC_OpenStream(long *nPort)
{
    if (!nPort)
    {
        return false;
    }

    HANDLE handle = H264_CreatePlayer(kProgramStream);
    *nPort = (long)handle;
    return true;
}

MONITOR_API bool XX_DEC_DisplayStream(long nPort, HWND hPlayWnd)
{
    HANDLE handle = (HANDLE)nPort;
    BOOL ret = H264_SetVideoWnd(handle, hPlayWnd);
    H264_Play(handle);
    return (ret == TRUE);
}

MONITOR_API bool XX_DEC_InputData(
                                  long nPort,
                                  char *pBuf,
                                  long nSize)
{
    HANDLE handle = (HANDLE)nPort;
    BOOL ret = H264_InputData(handle, (const BYTE*)pBuf, nSize);
    return (ret == TRUE);
}






void MyH264DecodeCallback(HANDLE handle, unsigned char* pBuf, int size,
                                    int width, int height, int fmt,
                                    void* pUser)
{
    CallBackContext context;
    if (!findCallBackContext(handle, context))
    {
        return;
    }

    if (context.cb)
    {
        (*context.cb)(context.port, (char*)pBuf, size, width, height, 0, context.user);
    }
}


MONITOR_API bool XX_DEC_SetVideoCallBack(
    long nPort,
    VideoCallBack fVideoCallBack,
    long nUser)
{
    HANDLE handle = (HANDLE)nPort;
    
    CallBackContext context;
    context.cb = fVideoCallBack;
    context.port = nPort;
    context.user = nUser;

    addCallBackContext(handle, context);

    H264_SetDecodeCallback(handle, MyH264DecodeCallback, handle);

    return true;
}

MONITOR_API bool XX_DEC_CloseStream(long nPort)
{
    HANDLE handle = (HANDLE)nPort;
    H264_Stop(handle);
    H264_DestroyPlayer(handle);

    removeCallBackContext(handle);

    return true;
}

